import {
  computed,
  createVNode,
  defineComponent,
  onMounted,
  onUnmounted,
  reactive,
  ref,
  render,
  provide,
  inject,
} from "vue";

export const DropdownItem = defineComponent({
  props: {
    label: String,
    icon: String,
  },
  setup(props) {
    let hide = inject("hide");
    return () => (
      <div class="dropdown-item" onClick={hide}>
        <i class={props.icon}></i>
        <span>{props.label}</span>
      </div>
    );
  },
});

const DropdownComponent = defineComponent({
  props: {
    option: { type: Object },
  },
  setup(props, ctx) {
    const state = reactive({
      option: props.option,
      isShow: false,
      top: 0,
      left: 0,
    });
    // 让外界通过虚拟节点显示和隐藏组件
    ctx.expose({
      showDropdown(option) {
        state.option = option;
        state.isShow = true;
        let { top, left, height } = option.el.getBoundingClientRect();
        state.top = top + height;
        state.left = left;
      },
    });

    provide("hide", () => (state.isShow = false));

    const classes = computed(() => [
      "dropdown",
      { "dropdown-isShow": state.isShow },
    ]);
    const el = ref(null);
    const onMousedownDocument = (e) => {
      // 如果点击的是dropdown内部 什么都不做
      if (!el.value.contains(e.target)) {
        state.isShow = false;
      }
    };

    onMounted(() => {
      // 事件传递先捕获再冒泡
      //之前为了阻止事件传播，我们给block都增加了stopPropagation
      document.body.addEventListener("mousedown", onMousedownDocument, true);
    });

    onUnmounted(() => {
      document.body.removeEventListener("mousedown", onMousedownDocument);
    });

    const styles = computed(() => ({
      top: state.top + "px",
      left: state.left + "px",
    }));
    return () => {
      return (
        <div class={classes.value} style={styles.value} ref={el}>
          {state.option.content()}
        </div>
      );
    };
  },
});

let vm;
export function $dropDown(option) {
  // 手动挂载组件
  // 如果组件已经存在只需要显示就行了
  if (!vm) {
    let el = document.createElement("div");
    // 创建虚拟节点
    vm = createVNode(DropdownComponent, { option });
    // 渲染虚拟节点:
    // 1.将组件渲染到el元素上
    render(vm, el);
    // 2.将el元素渲染到页面上
    document.body.appendChild(el);
  }

  // 显示弹窗组件
  let { showDropdown } = vm.component.exposed;
  showDropdown(option);
}
